﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Lidgren.Network;

namespace NetworkDemo
{
    public class PlayerManager
    {
        public PlayerManager(Game1 model)
        {
            gameModel = model;
        }

        #region Fields

        List<int> freeIds = new List<int>();
        Game1 gameModel;
        const ushort maxPlayerCount = 32;
        #endregion

        #region Properties
        List<Player> playersList = new List<Player>();
        public List<Player> PlayersList
        {
            get { return playersList; }
        }

        Player clientPlayer;
        public Player ClientPlayer
        {
            get { return clientPlayer; }
            set { clientPlayer = value; }
        }

        #endregion

        #region Public methods
        #region ID pool
        public int GetAvailableID()
        {
            if (playersList.Count >= maxPlayerCount) return -1;
            if (freeIds.Count < 1)
                return playersList.Count + 1;
            int val = freeIds.ElementAt<int>(0);
            freeIds.Remove(val);
            return (short)val;
        }

        public void FreeID(int n)
        {
            if (n < 1 || n > maxPlayerCount) return;

            if (n != playersList.Count)
            {
                freeIds.Add(n);
            }
        }
        #endregion

        #region Player Management
        public Player GetPlayer(int num)
        {
            return playersList.Find(delegate(Player P) { return P.MyNumber == num; });
        }

        public Player CreatePlayer(string pName, int pNumber, Vector2 pPos)
        {
            if (playersList.Count >= maxPlayerCount) return null; // No more players!
            if (GetPlayer(pNumber) != null) return null;
            Player P = new Player(gameModel.Content.Load<Texture2D>("relm"), pName, pNumber, pPos);
            AddPlayer(P);
            return P;
        }

        public void AddPlayer(Player p)
        {
            lock (playersList)
            {
                playersList.Add(p);
            }
        }

        public void RemPlayer(Player p)
        {
            lock (playersList)
            {
                playersList.Remove(p);
            }
        }

        public List<Player> GetAllPlayers()
        {
            return playersList.FindAll(delegate(Player P) { return P.MyNumber != 0; });
        }


        public void UpdatePlayers(NetBuffer S)
        {
            UInt32 numPlayers = S.ReadUInt32(3);
            Console.WriteLine("Updating " + numPlayers + " players");
            while (numPlayers-- > 0)
            {
                UpdatePlayer(S);
            }
        }
        public void UpdatePlayer(NetBuffer buff)
        {
            UInt32 pID = buff.ReadUInt32(3);
            Vector2 pPos = new Vector2(buff.ReadSingle(), buff.ReadSingle());
            string pName = buff.ReadString();
            UpdatePlayer(pName, (int)pID, pPos);
        }

        public void UpdatePlayer(string pName, int pNum, Vector2 sPos)
        {
            Player P = GetPlayer(pNum);
            if ((P = GetPlayer(pNum)) == null)
            {
                CreatePlayer(pName, pNum, sPos);
                return;
            }

            lock (P)
            {
                P.MyName = pName;
                lock (P.MySprite)
                {
                    P.MySprite.Position = sPos;
                }
            }
        }
        #endregion
        #endregion
    }
}
